package com.oglvip.business.remote.support.init;

import com.oglvip.business.remote.support.annotation.RestClient;
import com.oglvip.business.remote.support.proxy.ProxyFactory;
import com.oglvip.business.remote.support.scan.IScan;
import com.oglvip.business.remote.support.scan.PackageLoaderScan;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.Path;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class ServiceLoader {

    private final static Logger logger_ = LoggerFactory.getLogger(ServiceLoader.class);

    private String packageScan;

    private ProxyFactory proxyFactory;

    public ServiceLoader(String packageScan) {
        this(packageScan, new ProxyFactory());
    }

    public ServiceLoader(String packageScan, ProxyFactory proxyFactory) {
        this.packageScan = packageScan;
        this.proxyFactory = proxyFactory;
    }

    /**
     * Map<beanName,service>
     */
    private Map<Class<?>, Object> services = new ConcurrentHashMap<Class<?>, Object>();
    private static boolean loaded = false;

    public <T> T getService(Class<T> clazz) {
        return (T) services.get(clazz);
    }

    public Map<Class<?>, Object> getServices() {
        return services;
    }


    public synchronized void init() {
        if (loaded) {
            return;
        }
        scan();
        loaded = true;
    }

    void scan() {
        if (StringUtils.isBlank(packageScan)) {
            throw new IllegalArgumentException("package cant be null or empty!");
        }
        IScan scan = new PackageLoaderScan();
        Set<Class<?>> inters = scan.scan(packageScan, RestClient.class);
        for (Class<?> inter : inters) {
            load(inter);
        }
    }

    public void load(Class<?> inter) {
        if (!inter.isInterface()) {
            logger_.info(inter.getName() + " is not Interface");
            return;
        }

        if (inter.getAnnotation(Path.class) == null) {
            logger_.error(inter + "" + "is not annotation RestClient");
            return;
        }

        if (inter.getAnnotation(RestClient.class) == null) {
            logger_.error(inter + " " + "RestClient annotation is not appointed");
            return;
        }

        String host = inter.getAnnotation(RestClient.class).value();
        if (host == null) {
            logger_.error(inter + " " + "RestClient annotation is not appointed");
            return;
        }

        loadProxy(inter, host);
    }

    private void loadProxy(Class<?> inter, String host) {
        if (host != null) {
            ProxyFactory.addHost(inter, host);
        }
        Object proxy = null;
        try {
            proxy = proxyFactory.createProxy(inter);
        } catch (InstantiationException e1) {
            e1.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        this.services.put(inter, proxy);
    }

}
